{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "47f818ba-fe67-401c-b913-db13233d778b",
   "metadata": {},
   "source": [
    "# 任务要求\n",
    "### 调用API实现Svm，预测哪些乘客被异常运送。\n",
    "### 将Svm封装为函数Svm()。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "595c9b54-cc2f-400d-8d7f-cc87a8a55fb2",
   "metadata": {},
   "source": [
    "### 导入必要的包"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "1ca88d79-5eba-4b61-9821-7b5e2399a1e6",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.svm import SVC\n",
    "from sklearn.feature_selection import RFECV\n",
    "import pandas as pd\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2b79b486-29b5-4c14-a255-087dc6590188",
   "metadata": {},
   "source": [
    "### 对数据集进行特征选择\n",
    "\n",
    "* 对已经进行了缺省值填充和异常值处理的数据集 `refreshed_train.csv` 和 `refreshed_test.csv` 进一步进行特征选择。\n",
    "* 将特征选择后的数据集保存为csv文件"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6c9ed1b6-c270-4554-874b-f22ef4b07c15",
   "metadata": {},
   "source": [
    "# 分别从 train.csv 和 test.csv中读取出训练集和测试集\n",
    "train_data = pd.read_csv('RefreshedData/refreshed_train.csv')\n",
    "test_data = pd.read_csv('RefreshedData/refreshed_test.csv')\n",
    "X_train = train_data.iloc[:, :-1].values\n",
    "y_train = train_data.iloc[:, -1].values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "ce52374a-ae69-43c3-befb-ea615e7d3ae9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 构建 Svm 分类器\n",
    "clf = SVC(kernel='linear', C=1)\n",
    "rfecv = RFECV(estimator=clf, step=1, cv=5, verbose=2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "367e6f2e-0bb2-41db-a510-ec734c89ae93",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Fitting estimator with 17 features.\n",
      "Fitting estimator with 16 features.\n",
      "Fitting estimator with 15 features.\n",
      "Fitting estimator with 14 features.\n",
      "Fitting estimator with 13 features.\n",
      "Fitting estimator with 12 features.\n",
      "Fitting estimator with 11 features.\n",
      "Fitting estimator with 10 features.\n",
      "Fitting estimator with 9 features.\n",
      "Fitting estimator with 8 features.\n",
      "Fitting estimator with 7 features.\n",
      "Fitting estimator with 6 features.\n",
      "Fitting estimator with 5 features.\n",
      "Fitting estimator with 4 features.\n",
      "Fitting estimator with 3 features.\n",
      "Fitting estimator with 2 features.\n",
      "Fitting estimator with 17 features.\n",
      "Fitting estimator with 16 features.\n",
      "Fitting estimator with 15 features.\n",
      "Fitting estimator with 14 features.\n",
      "Fitting estimator with 13 features.\n",
      "Fitting estimator with 12 features.\n",
      "Fitting estimator with 11 features.\n",
      "Fitting estimator with 10 features.\n",
      "Fitting estimator with 9 features.\n",
      "Fitting estimator with 8 features.\n",
      "Fitting estimator with 7 features.\n",
      "Fitting estimator with 6 features.\n",
      "Fitting estimator with 5 features.\n",
      "Fitting estimator with 4 features.\n",
      "Fitting estimator with 3 features.\n",
      "Fitting estimator with 2 features.\n",
      "Fitting estimator with 17 features.\n",
      "Fitting estimator with 16 features.\n",
      "Fitting estimator with 15 features.\n",
      "Fitting estimator with 14 features.\n",
      "Fitting estimator with 13 features.\n",
      "Fitting estimator with 12 features.\n",
      "Fitting estimator with 11 features.\n",
      "Fitting estimator with 10 features.\n",
      "Fitting estimator with 9 features.\n",
      "Fitting estimator with 8 features.\n",
      "Fitting estimator with 7 features.\n",
      "Fitting estimator with 6 features.\n",
      "Fitting estimator with 5 features.\n",
      "Fitting estimator with 4 features.\n",
      "Fitting estimator with 3 features.\n",
      "Fitting estimator with 2 features.\n",
      "Fitting estimator with 17 features.\n",
      "Fitting estimator with 16 features.\n",
      "Fitting estimator with 15 features.\n",
      "Fitting estimator with 14 features.\n",
      "Fitting estimator with 13 features.\n",
      "Fitting estimator with 12 features.\n",
      "Fitting estimator with 11 features.\n",
      "Fitting estimator with 10 features.\n",
      "Fitting estimator with 9 features.\n",
      "Fitting estimator with 8 features.\n",
      "Fitting estimator with 7 features.\n",
      "Fitting estimator with 6 features.\n",
      "Fitting estimator with 5 features.\n",
      "Fitting estimator with 4 features.\n",
      "Fitting estimator with 3 features.\n",
      "Fitting estimator with 2 features.\n",
      "Fitting estimator with 17 features.\n",
      "Fitting estimator with 16 features.\n",
      "Fitting estimator with 15 features.\n",
      "Fitting estimator with 14 features.\n",
      "Fitting estimator with 13 features.\n",
      "Fitting estimator with 12 features.\n",
      "Fitting estimator with 11 features.\n",
      "Fitting estimator with 10 features.\n",
      "Fitting estimator with 9 features.\n",
      "Fitting estimator with 8 features.\n",
      "Fitting estimator with 7 features.\n",
      "Fitting estimator with 6 features.\n",
      "Fitting estimator with 5 features.\n",
      "Fitting estimator with 4 features.\n",
      "Fitting estimator with 3 features.\n",
      "Fitting estimator with 2 features.\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<style>#sk-container-id-2 {color: black;background-color: white;}#sk-container-id-2 pre{padding: 0;}#sk-container-id-2 div.sk-toggleable {background-color: white;}#sk-container-id-2 label.sk-toggleable__label {cursor: pointer;display: block;width: 100%;margin-bottom: 0;padding: 0.3em;box-sizing: border-box;text-align: center;}#sk-container-id-2 label.sk-toggleable__label-arrow:before {content: \"▸\";float: left;margin-right: 0.25em;color: #696969;}#sk-container-id-2 label.sk-toggleable__label-arrow:hover:before {color: black;}#sk-container-id-2 div.sk-estimator:hover label.sk-toggleable__label-arrow:before {color: black;}#sk-container-id-2 div.sk-toggleable__content {max-height: 0;max-width: 0;overflow: hidden;text-align: left;background-color: #f0f8ff;}#sk-container-id-2 div.sk-toggleable__content pre {margin: 0.2em;color: black;border-radius: 0.25em;background-color: #f0f8ff;}#sk-container-id-2 input.sk-toggleable__control:checked~div.sk-toggleable__content {max-height: 200px;max-width: 100%;overflow: auto;}#sk-container-id-2 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {content: \"▾\";}#sk-container-id-2 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-2 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-2 input.sk-hidden--visually {border: 0;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);height: 1px;margin: -1px;overflow: hidden;padding: 0;position: absolute;width: 1px;}#sk-container-id-2 div.sk-estimator {font-family: monospace;background-color: #f0f8ff;border: 1px dotted black;border-radius: 0.25em;box-sizing: border-box;margin-bottom: 0.5em;}#sk-container-id-2 div.sk-estimator:hover {background-color: #d4ebff;}#sk-container-id-2 div.sk-parallel-item::after {content: \"\";width: 100%;border-bottom: 1px solid gray;flex-grow: 1;}#sk-container-id-2 div.sk-label:hover label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-2 div.sk-serial::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: 0;}#sk-container-id-2 div.sk-serial {display: flex;flex-direction: column;align-items: center;background-color: white;padding-right: 0.2em;padding-left: 0.2em;position: relative;}#sk-container-id-2 div.sk-item {position: relative;z-index: 1;}#sk-container-id-2 div.sk-parallel {display: flex;align-items: stretch;justify-content: center;background-color: white;position: relative;}#sk-container-id-2 div.sk-item::before, #sk-container-id-2 div.sk-parallel-item::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: -1;}#sk-container-id-2 div.sk-parallel-item {display: flex;flex-direction: column;z-index: 1;position: relative;background-color: white;}#sk-container-id-2 div.sk-parallel-item:first-child::after {align-self: flex-end;width: 50%;}#sk-container-id-2 div.sk-parallel-item:last-child::after {align-self: flex-start;width: 50%;}#sk-container-id-2 div.sk-parallel-item:only-child::after {width: 0;}#sk-container-id-2 div.sk-dashed-wrapped {border: 1px dashed gray;margin: 0 0.4em 0.5em 0.4em;box-sizing: border-box;padding-bottom: 0.4em;background-color: white;}#sk-container-id-2 div.sk-label label {font-family: monospace;font-weight: bold;display: inline-block;line-height: 1.2em;}#sk-container-id-2 div.sk-label-container {text-align: center;}#sk-container-id-2 div.sk-container {/* jupyter's `normalize.less` sets `[hidden] { display: none; }` but bootstrap.min.css set `[hidden] { display: none !important; }` so we also need the `!important` here to be able to override the default hidden behavior on the sphinx rendered scikit-learn.org. See: https://github.com/scikit-learn/scikit-learn/issues/21755 */display: inline-block !important;position: relative;}#sk-container-id-2 div.sk-text-repr-fallback {display: none;}</style><div id=\"sk-container-id-2\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>RFECV(cv=5, estimator=SVC(C=1, kernel=&#x27;linear&#x27;), verbose=2)</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item sk-dashed-wrapped\"><div class=\"sk-label-container\"><div class=\"sk-label sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-4\" type=\"checkbox\" ><label for=\"sk-estimator-id-4\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">RFECV</label><div class=\"sk-toggleable__content\"><pre>RFECV(cv=5, estimator=SVC(C=1, kernel=&#x27;linear&#x27;), verbose=2)</pre></div></div></div><div class=\"sk-parallel\"><div class=\"sk-parallel-item\"><div class=\"sk-item\"><div class=\"sk-label-container\"><div class=\"sk-label sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-5\" type=\"checkbox\" ><label for=\"sk-estimator-id-5\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">estimator: SVC</label><div class=\"sk-toggleable__content\"><pre>SVC(C=1, kernel=&#x27;linear&#x27;)</pre></div></div></div><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-6\" type=\"checkbox\" ><label for=\"sk-estimator-id-6\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">SVC</label><div class=\"sk-toggleable__content\"><pre>SVC(C=1, kernel=&#x27;linear&#x27;)</pre></div></div></div></div></div></div></div></div></div></div>"
      ],
      "text/plain": [
       "RFECV(cv=5, estimator=SVC(C=1, kernel='linear'), verbose=2)"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rfecv.fit(X_train, y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "00e9ce2a-7178-40b8-8063-573d22bac7d9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ True  True  True  True  True  True  True  True  True  True  True  True\n",
      "  True  True  True  True  True]\n"
     ]
    }
   ],
   "source": [
    "# 得出 frame 各属性的 bool 索引\n",
    "support_train_index = list(rfecv.support_) + [True]\n",
    "support_test_index = list(rfecv.support_)\n",
    "print(rfecv.support_)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "50557b61-28b7-4cbc-b795-f997bd794059",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 选择 bool 索引中为 True 的属性，反之丢弃\n",
    "train_selected = train_data.loc[:, support_train_index]\n",
    "test_selected = test_data.loc[:, support_test_index]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "0c6902f4-e1ec-4cbb-8fb6-5b93ba32c373",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 将选择的数据集保存\n",
    "train_selected.to_csv('FeatureSelectedData/svm_train.csv', index=False)\n",
    "test_selected.to_csv('FeatureSelectedData/svm_test.csv', index=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bb46200e-15af-4d75-9101-29e08e6a724c",
   "metadata": {},
   "source": [
    "### 训练 `Svm` 并保存\n",
    "\n",
    "* 读取特征选择后的数据集，路径为 `FeatureSelectedData/svm_train.csv`\n",
    "* 保存路径为 `/model/svm_model.pkl`"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "22ac4fc3-9e3b-4633-8540-4db706df4ed6",
   "metadata": {},
   "source": [
    "### 导入保存/加载模型用的包： `joblib` 中的 `dump`, `load`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "35d738a7-ab6b-4de8-9c1e-3eae752761d7",
   "metadata": {},
   "outputs": [],
   "source": [
    "from joblib import dump, load"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a9e99712-6341-4f6b-94a9-188949544c4e",
   "metadata": {},
   "source": [
    "### 加载数据集并训练 Svm 分类器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "fe4a8797-a4f3-4838-8788-6c496702bf33",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model saved as svm_model.joblib\n"
     ]
    }
   ],
   "source": [
    "final_train_data = pd.read_csv('FeatureSelectedData/svm_train.csv')\n",
    "final_X_train = final_train_data.iloc[:, :-1]\n",
    "final_y_train = final_train_data.iloc[:, -1]\n",
    "\n",
    "clf.fit(final_X_train, final_y_train)\n",
    "\n",
    "dump(clf, 'model/svm_model.joblib')\n",
    "print(\"Model saved as svm_model.joblib\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d6a07eba-91b6-448f-a440-0c781c70c9d9",
   "metadata": {},
   "source": [
    "### 将 `Svm` 模型封装为 `Svm()` 函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "f7c4a7d7-2c75-4d89-9cb7-87bd26bf8403",
   "metadata": {},
   "outputs": [],
   "source": [
    "def Svm(test_data):\n",
    "    clf = load('model/svm_model.joblib')\n",
    "    y_predicted = clf.predict(test_data)\n",
    "    return y_predicted"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c93882da-de61-47df-bac3-4da2874e7dfd",
   "metadata": {},
   "source": [
    "### 调用 `Svm()` 函数对测试集进行预测\n",
    "将预测结果输出为 `result_svm.csv`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "c77d84bd-f576-41bc-9f21-d5ed1e77daed",
   "metadata": {},
   "outputs": [],
   "source": [
    "final_test_data = pd.read_csv('FeatureSelectedData/svm_test.csv')\n",
    "result_file = pd.read_csv('sample_submission.csv')\n",
    "predictions = Svm(final_test_data)\n",
    "result_file[\"Transported\"] = pd.Series(predictions, result_file.index)\n",
    "result_file.to_csv('predictions/result_svm.csv', index=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2d90bfcc-c500-4614-9473-a4ae654ac173",
   "metadata": {},
   "source": [
    "### 将 `result_svm.csv` 上传到 `kaggle` 上评分"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
